package lz.controls.text
{

	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.geom.Rectangle;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.utils.Dictionary;

	import lz.controls.core.UIComponent;
	/**
	 *富文本line 
	 * @author lake
	 * 
	 */	
	public class LineTxt extends UIComponent
	{
		/**
		 *表情容器 
		 */		
		protected var _faceContainer		:Sprite;
		/**
		 *文本内容 
		 */		
		protected var _text				:TextField;
		/**
		 *文本格式 
		 */		
		protected var _textFormat			:TextFormat;
		/**
		 *文本值 
		 */		
		protected var _textValue			:String;
		/**
		 *表情dic 
		 */		
		protected var _faceDic				:Dictionary;
		/**
		 *表情列表 
		 */		
		protected var _faceList			:Array;
		/**
		 *滤镜 
		 */		
		protected var _filters:Array=[];
		/**
		 *构造函数 
		 * @param width
		 * @param faceDic
		 * 
		 */
		public function LineTxt(width:int=100, faceDic:Dictionary=null)
		{
			super();
			super.width=width;
			_faceDic=(faceDic) ? faceDic : new Dictionary();
		}
		/**
		 *设置内容 
		 * @param value
		 * 
		 */
		public function set text(value:String):void
		{
			if (_textValue == value)
				return;
			if (_text == null)
			{
				createTextField();
				if (_textFormat)
				{
					_text.defaultTextFormat=_textFormat;
					_text.selectable=false; // modify
				}
				else
				{
					var tf:TextFormat=getDefalutTextFormat();
					_text.defaultTextFormat=tf;
					_text.setTextFormat(tf);
					_text.selectable=false; // modify
				}
			}
			_textValue=value;
			update();
		}
		/**
		 *清理 
		 * 
		 */
		public function clear():void
		{
			if (_text)
				_text.htmlText="";
			if (_faceList)
			{
				while (_faceList.length > 0)
				{
					var obj:Object=_faceList.shift();
					if (_faceContainer && obj.face && _faceContainer.contains(obj.face))
					{
						_faceContainer.removeChild(obj.face);
					}
					obj.face=null;
					obj=null;
				}
			}
			_faceList=[];
		}
		/**
		 *销毁 
		 * 
		 */
		override public function destroy():void
		{
			super.destroy();
			_filters=[];
			clear();
			_textValue="";
			if (_text && contains(_text))
			{
				removeChild(_text);
				_text=null;
			}
			if (_faceContainer && contains(_faceContainer))
			{
				removeChild(_faceContainer);
				_faceContainer=null;
			}
			_faceList=null;
			_faceDic=null;
			_textFormat=null;
		}
		/**
		 *设置宽度 
		 * @param value
		 * 
		 */
		override public function set width(value:Number):void
		{
			if (_width != value)
			{
				_width=value;
				update();
			}
		}
		/**
		 *更新 
		 * 
		 */
		private function update():void
		{
			clear();
			_text.width=width;
			_text.defaultTextFormat=textFormat;
			parseFace();
			if (fillFace() == false)
				return;
			layout();
			addChild(_text);
			if (_faceContainer)
				addChild(_faceContainer);
//			trace(_text.height + "+"+_text.textHeight);
//			trace(_text.numLines);
			height=(_text == null || _text.text == "") ? 0 : _text.y + _text.textHeight + 2;
//			height=(_text == null || _text.text == "") ? 0 : _text.y + _text.numLines * 17;
			
		}
		/**
		 *布局 
		 * 
		 */
		private function layout():void
		{
			if (_faceList)
			{
				for each (var obj:Object in _faceList)
				{
					var lineIndex:int=_text.getLineIndexOfChar(obj.txtIndex);
					if (lineIndex == -1)
						continue;
					var lineHeight:int=_text.getLineMetrics(lineIndex).ascent + _text.getLineMetrics(lineIndex).descent;
					var preY:int=0;
					var preCharIndex:int=0;
					if (lineIndex > 0)
					{
						preCharIndex=_text.getLineOffset(lineIndex - 1);
						if (preCharIndex == -1)
							continue;
						preY=getCharBoundaries(_text, preCharIndex).y + _text.getLineMetrics(lineIndex - 1).ascent + _text.getLineMetrics(lineIndex - 1).descent;
					}
					if (obj.face)
						obj.face.y=Math.round(obj.face.y - (obj.face.height - lineHeight));
					if (lineIndex > 0 && (preY > obj.face.y))
					{
						var tf:TextFormat=_text.getTextFormat(preCharIndex, _text.getLineOffset(lineIndex) - 1);
						tf.leading+=preY - obj.face.y;
						_text.setTextFormat(tf, preCharIndex, _text.getLineOffset(lineIndex) - 1);
						updateFaceOfIndex(lineIndex, preY - obj.face.y);
					}
					else if (lineIndex == 0 && obj.face.y < 0)
					{
						_text.y=-obj.face.y;
						if (_faceContainer)
							_faceContainer.y=_text.y;
					}
				}
			}
		}
		/**
		 *更新表情 
		 * @param lineIndex
		 * @param offsetY
		 * 
		 */
		private function updateFaceOfIndex(lineIndex:int, offsetY:int):void
		{
			if (_faceList)
			{
				for each (var obj:Object in _faceList)
				{
					if (obj.lineIndex >= lineIndex && obj.face)
					{
						obj.face.y+=offsetY;
					}
				}
			}
		}
		private function getCharBoundaries(txtField:TextField, charIndex:int):Rectangle
		{
			var h:Number=txtField.height;
			txtField.height=txtField.textHeight;
			var rectTemp:Rectangle=txtField.getCharBoundaries(charIndex);
			txtField.height=h;
			return rectTemp;
		}
		private function fillFace():Boolean
		{
			var offsetIndex:int=0;
			if (_faceList == null)
				return true;
			for each (var obj:Object in _faceList)
			{
				if (obj.face)
				{
					if (_faceContainer == null)
						_faceContainer=new Sprite();
					var cc:Rectangle=getCharBoundaries(_text, obj.txtIndex);
					if (cc == null)
						continue;
					obj.face.x=Math.round(cc.x);
					obj.face.y=Math.round(cc.y);
					obj.lineIndex=_text.getLineIndexOfChar(obj.txtIndex);
					if (obj.face.x + obj.face.width > _text.width)
					{
						text=_textValue.substring(0, obj.index) + "\n" + _textValue.substring(obj.index);
						return false;
					}
					_faceContainer.addChild(obj.face);
					cc=null;
				}
			}
			return true;
		}
		private function parseFace():void
		{
			var myPattern:RegExp=getPattern();
			_text.htmlText=_textValue;
			if (myPattern == null || _textValue == "")
			{
				return;
			}
			_faceList=[];
			var txt:String=getTxt(_textValue);
			var html:String=_textValue;
			var obj:Object;
			var index:int=0;

			var macthStr:*=html.match(myPattern);
			while (macthStr)
			{
				obj=new Object();
				obj.index=macthStr["index"];
				obj.faceStr=macthStr[0];
				var face:DisplayObject=getFace(obj.faceStr);
				obj.face=face;
				if (face)
				{
					obj.replaceChars=getReplaceChars(face.width);
				}
				else
				{
					obj.replaceChars="";
				}
				html=html.replace(myPattern, getTempChar(macthStr[0].length));
				_faceList.push(obj);
				macthStr=html.match(myPattern);
			}

			html=_textValue;
			macthStr=html.match(myPattern);
			index=0;
			while (macthStr)
			{
				obj=_faceList[index];
				obj.htmlIndex=macthStr["index"];
				html=html.replace(myPattern, obj.replaceChars);
				macthStr=html.match(myPattern);
				index++;
			}

			macthStr=txt.match(myPattern);
			index=0
			while (macthStr)
			{
				obj=_faceList[index];
				obj.txtIndex=macthStr["index"];
				txt=txt.replace(myPattern, obj.replaceChars);
				macthStr=txt.match(myPattern);
				index++;
			}
			myPattern=null;
			_text.htmlText=html;
		}
		private function getTempChar(num:int):String
		{
			var s:String="";
			while (num > 0)
			{
				s+="f";
				num--;
			}
			return s;
		}
		private function getTxt(value:String):String
		{
			var tf:TextField=new TextField();
			tf.htmlText=value;
			return tf.text;
		}
		private function getReplaceChars(width:int):String
		{
			var str:String="";
			var tf:TextField=new TextField();
			var textF:TextFormat=textFormat;
			tf.defaultTextFormat=textF;
			tf.setTextFormat(textF);
			var w:int=0;
			while (str == "")
			{
				//str += "_";
				str+=" ";
				tf.text=str;
				w=tf.textWidth;
			}
			var count:int=Math.round(width / w);
			str="";
			for (var i:int=0; i < count; i++)
			{
				//str += "_";
				str+=" ";
			}
			return str;
		}
		private function getFace(value:String):DisplayObject
		{
			if (value == "" || value == null || !_faceDic[value])
			{
				return null;
			}
			return getDisplayObjectInstance(_faceDic[value]);
		}
		private function getPattern():RegExp
		{
			var str:String="";
			var arr:Array=new Array();
			for (var i:* in _faceDic)
			{
				arr.push(i);
			}
			arr.sort(onSort);
			str=arr.join("|");
			if (str == "")
			{
				return null;
			}
			return new RegExp(str);
		}
		private function onSort(str1:String, str2:String):int
		{
			if (str1.length > str2.length)
				return -1;
			if (str1.length < str2.length)
				return 1;
			return 0;
		}
		public function get text():String
		{
			return _textValue;
		}
		public function set textFormat(tf:TextFormat):void
		{
			_textFormat=tf;
			update();
		}
		public function get textFormat():TextFormat
		{
			if (_textFormat)
				return _textFormat;
			return getDefalutTextFormat();
		}
		protected function getDefalutTextFormat():TextFormat
		{
			var tf:TextFormat=new TextFormat();
			tf.font="SimSun";
			tf.leading=5;
			return tf;
		}
		private function createTextField():void
		{
			if (_text == null)
			{
				_text=new TextField();
				_text.autoSize=TextFieldAutoSize.LEFT;
				_text.filters=_filters;
				_text.mouseWheelEnabled=false;
				_text.multiline=true;
				_text.wordWrap=true;
				_text.border=false;
				_text.width=width;
			}
		}
		public function useFilter(arr:Array):void
		{
			if (arr == null)
				_filters=[];
			_filters=arr;
			if (_text)
				_text.filters=_filters;
		}
	}
}
